;;; smart-tab.el --- smart TAB completion

;; Copyright (C) 2011  Markus

;; Author: Markus <markus.prepens@googlemail.com>
;; Keywords: abbrev, wp

;; This program is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.

;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
;; GNU General Public License for more details.

;; You should have received a copy of the GNU General Public License
;; along with this program.  If not, see <http://www.gnu.org/licenses/>.

;;; Commentary:

;; This elisp code should improve the behavior of the two desired function for
;; the <tab> key: First, indent code or just text according to the major
;; mode. Second, complete text or symbols.
;;
;; Each major mode has its own standard binding for the TAB key. Therefore, it
;; makes no sense rebind the TAB key to a custom functions which handles all
;; major modes. Thats why this file contains functions or a dedicaes major mode.
;;
;; Right now python-mode, c-mode and c++-mode is supported.
;;


;;; Code:


(defun my-smart-c-completion-or-indent()
  "Text will be completed with `hippie-expand' when function is
called right after typing a part of the text to be completed.
Calling this function repeatedly cycles through the completion
candidates.

Otherwise the current line will be indent by
`c-indent-line-or-region'. When a region is marked, the whole
region will be indented by `c-indent-line-or-region'."
  (interactive)
  (if mark-active
      (c-indent-line-or-region (region-beginning) (region-end))
    (if (functionp last-command)
        (if (and (or (eq last-command 'self-insert-command)
                     (eq last-command 'my-smart-c-completion-or-indent))
                 (looking-at "\\_>"))
            (hippie-expand nil)
          (c-indent-line-or-region))
      (c-indent-line-or-region))))

(add-hook 'c-mode-common-hook
          (lambda ()
            (local-set-key (kbd "<tab>") 'my-smart-c-completion-or-indent)))


(defun my-extend-region()
  "A support function to extend the marked region to entire
lines. The `python-shift-left' or `python-shift-right' functions
does not shift lines when only a portion is part of the active
region. Only call this function when `mark-active' is non-nil."
  (if (< (mark) (point))
      (progn
        (end-of-line)
        (exchange-point-and-mark)
        (beginning-of-line))
    (progn
      (beginning-of-line)
      (exchange-point-and-mark)
      (end-of-line))))

(defun my-smart-python-completion-or-indent()
  "Text will be completed with `hippie-expand' when function is
called right after typing a part of the text to be completed.
Calling this function repeatedly cycles through the completion
candidates.

 Otherwise the current line will be shifted right by
`python-indent'. When a region is marked, the whole region will
be shifted right by `python-indent'."
  (interactive)
  (if mark-active
      (save-excursion
        (my-extend-region)
        (python-shift-right (region-beginning) (region-end)))
    (if (functionp last-command)
        (if (and (or (eq last-command 'self-insert-command)
                     (eq last-command 'my-smart-python-completion-or-indent))
                 (looking-at "\\_>"))
            (hippie-expand nil)
          (python-shift-right (line-beginning-position) (line-end-position)))
      (python-shift-right (line-beginning-position) (line-end-position)))))

(defun my-smart-python-unindent()
  "The current line will be shifted left by `python-indent'. When
a region is marked, the whole region will be shifted left by
`python-indent'."
  (interactive)
  (if mark-active
      (progn
        (my-extend-region)
        (python-shift-left (region-beginning) (region-end)))
    (python-shift-left (line-beginning-position) (line-end-position))))

(add-hook 'python-mode-hook
          (lambda ()
            (local-set-key (kbd "<tab>") 'my-smart-python-completion-or-indent)
            (local-set-key (kbd "S-<tab>") 'my-smart-python-unindent)))



(provide 'resource/smart-tab)
;;; smart-tab.el ends here
